/*jslint sloppy: true, indent: 2, vars: true, todo: true, browser: true */
/**
 *
 * Perform jQuery library
 * Developed by Perform
 *
 * Built on top of the jQuery library
 * http://jquery.com
 *
 * Description: wrapes basic functionality needed on almost every page
 * Version: 1.0 - isLoggedIn()
 *              - isSubscribed()
 *              - isAboutToChurn
 *              - isChurned()
 *              - getSubscriberDefnTags()
 *              - isEventPermitted()
 *              - logout()
 *              - getCurrentTimeStamp()
 *              - getUserDetails()
 *              - getCookie()
 *              - setCookie()
 *              - deleteCookie()
 *              - getChip()
 *              - setChip()
 *              - deleteChip()
 *              - refreshUserCookie()
 *              - setLogoutRedirect()
 */
 
/**
 * Adds indexOf method for arrays (IE7/IE8 fix)
 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
 */
if (!Array.prototype.indexOf) {
  Array.prototype.indexOf = function (searchElement , fromIndex) {
    var i,
        pivot = (fromIndex) ? fromIndex : 0,
        length;
    if (!this) {
      throw new TypeError();
    }
    length = this.length;
    if (length === 0 || pivot >= length) {
      return -1;
    }
    if (pivot < 0) {
      pivot = length - Math.abs(pivot);
    }
    for (i = pivot; i < length; i++) {
      if (this[i] === searchElement) {
        return i;
      }
    }
    return -1;
  };
} 
 
var perform = (function () {
    var COOKIE_DELIMITER = '; ', /*semicolon space*/
      COOKIE_VALUE_DELIMITER = '=', /*equals*/
      QUERY_STRING_PARAMS_DELIMITER = '&', /*&amp;*/
      QUERY_STRING_VALUE_DELIMITER = '=',  /*equals*/
      userLogedOutAutomaticaly = false,
      logoutRedirect = false;

    /**
     * getQueryStringDetails
     * get information about specific keyword in query string
     * @param query (string) query string
     * @param key (string) which keyword should be returned
     * @param pairsDeleimiter (string) [OPTIONAL] which string is used as delimiter of pairs
     *                                            by default QUERY_STRING_PARAMS_DELIMITER  constant is used
     * @param keyValueDelimiter (string) [OPTIONAL] which string is used as delimiter of key and valeu
     *                                              by default QUERY_STRING_VALUE_DELIMITER constant is used
     */
    function getQueryStringDetails(query, key, pairsDelimiter, keyValueDelimiter) {
      if (typeof pairsDelimiter !== 'string') {
        pairsDelimiter = QUERY_STRING_PARAMS_DELIMITER;
      }

      if (typeof keyValueDelimiter !== 'string') {
        keyValueDelimiter = QUERY_STRING_VALUE_DELIMITER;
      }

      // Strip double quotes from the beginning and end
      // of the cookie string
      if (query.charAt(0) === '"' && query.charAt(query.length - 1) === '"') {
        query = query.substring(1, query.length - 1);
      }

      if (key.indexOf(pairsDelimiter) === -1 && key.indexOf(keyValueDelimiter) === -1) {
        var pairsDelimiterLength = pairsDelimiter.length,
          search_arg = key + keyValueDelimiter,
          search_arg_length = search_arg.length,
          startPos = 0,
          queryLength = query.length;

        while (startPos <= queryLength - search_arg_length) {
          var endPos = query.indexOf(pairsDelimiter, startPos);
          if (endPos === -1) {
            endPos = queryLength; /*no more key/value pairs found*/
          }

          if (query.substring(startPos, startPos + search_arg_length) === search_arg) {
            /*we have found holy grail*/
            var details = {
              startPos : startPos,
              endPos : endPos,
              valueStartPos: startPos + search_arg_length,
              value: query.substring(startPos + search_arg_length, endPos)
            };
            return details;
          }
          startPos = endPos + pairsDelimiterLength;
        }
      }
      return false;
    };
  
	function serialize(obj) {
      var str = [];
      for(var p in obj)
        if (obj.hasOwnProperty(p)) {
          str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
        }
      return str.join("&");
    };

  	function extend(obj, defaults) {
      for (var i in defaults) {
        if (!obj[i]) {
          obj[i] = defaults[i];
        } else if(typeof defaults[i] === "object") {
          obj[i] = extend(obj[i], defaults[i]);
        }
      }
      return obj;
    };

    return {
      /**
       * perform.isLogedIn
       * Check whether user is logged in or not
       * If user cookie is corrupted, user is loged out automaticaly (this logout is called only once pre page view)
       * @return (boolean) true when user is logged in
       * @todo Single Sign On
       */
      isLoggedIn : function () {        
        var userCookie = perform.getCookie('user');        

        if (userCookie === false) {
          userCookie = '';
        }

        var userName = getQueryStringDetails(userCookie, 'username');
        if (userName !== false) {
          userName = userName.value;
        }
        var expireTimeStamp = getQueryStringDetails(userCookie, 'expiryTimestamp');
        if (expireTimeStamp !== false) {
          expireTimeStamp = expireTimeStamp.value;
        }
		var currentTimeStamp = perform.getCurrentTimeStamp();
        if ((userName !== false && userName !== '') || expireTimeStamp !== false) {
          if (userName  === false || userName === '' || expireTimeStamp === false || expireTimeStamp < currentTimeStamp) {
            if (!userLogedOutAutomaticaly) {
              userLogedOutAutomaticaly = true;
              perform.logout();
            }
          } else {
            return true;
          }
        }
        return false;
      },
     /**
       * perform.isSubscribed
       * Check whether user is subscribed or not
       * @param (array) [OPTIONAL] userInfo array containing user info, retrieved from  getUserDetails
       * @param (int) [OPTIONAL] siteId against which subscription should be checked
       * @return (boolean) true when user is subscribed
       * @todo Pay Per View functionality
       */
      isSubscribed : function (userInfo, siteId) {
        if (userInfo === undefined) {
          userInfo = perform.getUserDetails();
        }

        if (siteId === undefined) {
          return (userInfo.subscribed === 'yes');
        } else {
          var subscribedOrgns = [];
          if (typeof userInfo.subscribedOrgns !== 'undefined') {
            subscribedOrgns = userInfo.subscribedOrgns.split('|');
          }

          return (subscribedOrgns.indexOf(siteId.toString()) !== -1);
        }
      },

      /**
       * Check if user is going to churn
       * @param userInfo (object) [OPTIONAL] user info retrieved from getUserDetails function
       * @return (boolean|object) in case user is not going to churn returns fallse
       *                          otherwise object containig following properties is provided
       *         - reason (string) repeatCancelled or repeatWillFail in case not availiable unknown
       *         - churnDate (string|boolean) date in format DD/MM/YYYY, in case not availiable false
       *         - cardExpiry (string|boolean) date in format DD/MM/YYYY, in case not availiable false
       * @see - http://helpdesk.premiumtv.co.uk/mediawiki/index.php/Subscriber_Defn_-_Basic_Info
       */
      isAboutToChurn : function (userInfo) {
        if (userInfo === undefined) {
          userInfo = perform.getUserDetails();
        }

        var userDefnTags = perform.getSubscriberDefnTags(userInfo);

        if (userDefnTags.indexOf('churnPending') !== -1) {
          var response = {};
          if (userDefnTags.indexOf('repeatCancelled') !== -1) {
            response.reason = 'repeatCancelled';
            if (typeof userInfo.churnDate !== 'undefined') {
              response.churnDate = userInfo.churnDate;
            } else {
              response.churnDate = false;
            }
          } else if (userDefnTags.indexOf('repeatWillFail') !== -1) {
            response.reason = 'repeatWillFail';
            if (typeof userInfo.cardExpiry !== 'undefined') {
              response.cardExpiry = userInfo.cardExpiry;
            } else {
              response.cardExpiry = false;
            }
          } else {
            response.reason = 'unknown';
          }
          return response;
        }

        return false;
      },
      
      /**
       * perform.isEmailVerified                                                                                                                   
       * Check whether user has email verified or not
       * @param (array) [OPTIONAL] userInfo array containing user info, retrieved from  getUserDetails
       * @return (boolean)
       */
      isEmailVerified : function (userInfo) {
        if (userInfo === undefined) {
          userInfo = perform.getUserDetails();
        }
        return (userInfo.verifiedDate != undefined);
      },

      /**
       * Check if user has churned already
       * @param userInfo (object) [OPTIONAL] user info retrieved from getUserDetails function
       * @return (boolean|sring) in case user is not churned returns fallse
       *                          otherwise string representing reason (repeatFailed|repeatCancelled|repeatNone|unknown)
       * @see - http://helpdesk.premiumtv.co.uk/mediawiki/index.php/Subscriber_Defn_-_Basic_Info
       */
      isChurned : function (userInfo) {
        if (userInfo === undefined) {
          userInfo = perform.getUserDetails();
        }

        var userDefnTags = perform.getSubscriberDefnTags(userInfo);

        if (userDefnTags.indexOf('churnComplete') !== -1) {
          var reasons = ['repeatFailed', 'repeatCancelled', 'repeatNone'],
            i;
          for (i = 0; i < reasons.length; i += 1) {
            if (userDefnTags.indexOf(reasons[i]) !== -1) {
              return reasons[i];
            }
          }
          return 'unknown';
        }
        return false;
      },

      /**
       * Get subscriber definition tags
       * @param userInfo (object) [OPTIONAL] - user info retrieved from getUserDetails function
       * @return (object) - list of subscriber definition tags, in case they are not provided returns empty array
       * @see - http://helpdesk.premiumtv.co.uk/mediawiki/index.php/Subscriber_Defn_-_Basic_Info
       */
      getSubscriberDefnTags : function (userInfo) {
        if (userInfo === undefined) {
          userInfo = perform.getUserDetails();
        }

        var userDefnTags = [];

        if (typeof userInfo.userDefnTags !== 'undefined') {
          userDefnTags = userInfo.userDefnTags.split('|');
        }

        return userDefnTags;
      },

      /**
       * perform.isEventPermitted
       * Check if event is permitted for the user (xml).
       */
      isEventPermitted : function (eventId, callback) {
        if (this.isLoggedIn()) {
          $.ajax({
            type: 'GET',
            dataType: 'xml',
            url: '/decision/global/decisions/eventPermissions/eventId/' + eventId,
            success: function (xml) {
              if ($(xml).find('event').length === 0) {
                callback(false);
              } else {
                $(xml).find('event').each(function () {
                  if ($(this).attr('id') == eventId) {
                    callback($('permitted', this).text());
                  }
                });
              }
            },
            error: function () {
              callback(false);
            }
          });
        } else {
          callback(false);
        }
      },
      logout: function () {
        var iframe = document.createElement("iframe");
        iframe.style.display = "none";
        iframe.src = "https://secure.ar.beinsports.net/system/userlogout";
        if (typeof iframe.readyState !== 'undefined') {
          iframe.onreadystatechange = function () {
            if (iframe.readyState === "complete") {
              if (logoutRedirect !== false) {
                window.location = logoutRedirect;
              } else {
                location.reload(true);
              }
            }
          };
        } else {
          iframe.onload = function () {
            if (logoutRedirect !== false) {
              window.location = logoutRedirect;
            } else {
              location.reload(true);
            }
          };
        }
        document.body.appendChild(iframe);
      },
      getCurrentTimeStamp: function () {
        var currentDate = new Date();
        return currentDate.getTime();
      },
      /**
       * perform.getUserDetails
       * Get all details from user cookie
       * @return (object) object containing all user details, in time of implementation following details were availiable:
       *                  - username
       *                  - creationdate
       *                  - lastupdatedate
       *                  - localecountrycode
       *                  - localelanguagecode
       *                  - title
       *                  - firstname
       *                  - lastname
       *                  - emailaddress
       *                  - subscribed
       */
      getUserDetails : function () {
        var user = perform.getCookie('user');
        if (user !== false && perform.isLoggedIn()) {
          if (user.charAt(0) === '"' && user.charAt(user.length - 1) === '"') {
            user = user.substring(1, user.length - 1);
          }

          var parts = user.split(QUERY_STRING_PARAMS_DELIMITER),
            details = {},
            i;

          for (i = 0; i < parts.length; i += 1) {
            var tmp = parts[i].split(QUERY_STRING_VALUE_DELIMITER),
              key = tmp.shift(),
              value = tmp.join(QUERY_STRING_VALUE_DELIMITER);
            details[key] = value;
          }
          return details;
        }
        return false;
      },
      /**
       * perform.getCookie
       * Get cookie indetified by name
       * @param (string) name name of cookie
       * @param (boolean) OPTION decode whether the cookie should be decoded, by default set to true
       * @return (boolean/string) returns cookie value, if not found false
       */
      getCookie : function (name, decode) {
        if (document.cookie && document.cookie !== '') {
          if (decode === undefined) {
            decode = true;
          }

          var details = getQueryStringDetails(document.cookie, name, COOKIE_DELIMITER, COOKIE_VALUE_DELIMITER);
          if (details !== false) {
            var cookie = details.value;
            if (decode) {
              cookie = decodeURIComponent(cookie);
            }
            return cookie;
          }
        }
        return false;
      },
      /**
       * perform.setCookie
       * Set cookie
       * @param (string) name
       * @param (string) value
       * @param (object) [OPTIONAL] options, following options are recognized
       *                 (date|number) expires.      If not specified, only session cookie is created
       *                                             If date is provided, this date object is used
       *                                             If integer is provided, it is used as offset in days from current date object
       *                 (string) path.              If not specified path is not specified in cookie
       *                 (string) domain             If not specified domain is not specified in cookie
       *                 (boolean) secure            If specified to true cookie is not mark as secure
       * @param (boolean) [OPTIONAL] encode If specified to false the value is not encoded before adding to cookie
       * @return (boolean) allways true
       */

      setCookie : function (name, value, options, encode) {
        if (encode === undefined) {
          encode = true;
        }

        var cookie = name + '=' + (encode ? encodeURIComponent(value) : value);
        options = options || {};

        /*Add path setting*/
        if (typeof options.path === 'string') {
          cookie = cookie + '; path=' + options.path;
        }

        /*Add expires setting*/
        if (typeof options.expires !== 'undefined' && (typeof options.expires === 'number' || typeof options.expires.toUTCString === 'function')) {
          var date;
          if (typeof options.expires === 'number') {
            date = new Date();
            date.setTime(date.getTime() + (options.expires * 86400000)); /*24*60*60*1000 - 1 day in miliseconds*/
          } else {
            date = options.expires;
          }
          cookie = cookie + '; expires=' + date.toUTCString();
        }

        /*Add domain settings*/
        if (typeof options.domain === 'string') {
          cookie = cookie + '; domain=' + options.domain;
        }

        /*Add secure settings*/
        if (typeof options.secure !== 'undefined' && options.secure === true) {
          cookie = cookie + '; secure';
        }

        document.cookie = cookie;
        return true;
      },
      /**
       * perform.deleteCookie
       * deleteCookie
       * @param name (string) name of cookie, which should be deleted
       * @param name (object) options, @see setCookie for more information
       * @return (boolean) true, when cookie was deleted
       */
      deleteCookie: function (name, options) {
        options = options || {};
        options.expires = -1;
        return perform.setCookie(name, '', options);
      },
      /**
       * perform.getChip
       * get chip of cookie (possible only when cookie is specified as query string)
       * @param cookieName (string) in which cookie is chip located
       * @param name (string) name of chip
       * @return (boolean|string) false, when cookie or chip was not found, otherwise value of chip
       */
      getChip: function (cookieName, name) {
        var cookie = perform.getCookie(cookieName);
        if (cookie !== false) {
          var chipDetails = getQueryStringDetails(cookie, name);
          if (chipDetails !== false) {
            return chipDetails.value;
          }
        }
        return false;
      },
      /**
       * perform.setChip
       * add chip to cookie
       * @param cookieName (string) to which cookie, chip should be added
       * @param name (string) name of chip
       * @param value (string) value that should be assigned to chip
       * @return (boolean) @see perform.setCookie
       * @WARNING - IT IS NOT RECOMENDED TO USE THIS FUNCTION
       *          - AFTER USE, EXPIRATION OF AFFECTED COOKIE IS CHANGED - TILL END OF SESSION
       */
      setChip: function (cookieName, name, value) {
        /* firstly delete old chip, so we do not have to care about replacing */
        perform.deleteChip(cookieName, name);
        var cookie = perform.getCookie(cookieName),
          chip = name + '=' + value;
        if (cookie !== false && cookie !== '') {
          return perform.setCookie(cookieName, cookie + '&' + chip);
        } else {
          return perform.setCookie(cookieName, chip);
        }
      },
      /**
       * perform.deleteChip
       * delete chip from cookie
       * @param cookieName (string) from which cookie, chip should be removed
       * @param name (string) name of chip, that should be removed
       * @return (boolean) false when chip/cookie was not found, otherwise @see set cookie
       * @WARNING - IT IS NOT RECOMENDED TO USE THIS FUNCTION
       *          - AFTER USE, EXPIRATION OF AFFECTED COOKIE IS CHANGED - TILL END OF SESSION
       */
      deleteChip: function (cookieName, name) {
        var cookie = perform.getCookie(cookieName);
        if (cookie !== false) {
          var chipDetails = getQueryStringDetails(cookie, name);
          if (chipDetails !== false) {
            var beforeChip = '';
            var afterChip = '';
            if (chipDetails.startPos !== 0) {
              beforeChip = cookie.substring(0, chipDetails.startPos - 1);
            }

            if (chipDetails.endPos < cookie.length) {
              afterChip = cookie.substring(chipDetails.endPos + 1, cookie.length);
            }

            cookie = beforeChip + ((beforeChip !== '' && afterChip !== '') ? '&' : '') + afterChip;

            return perform.setCookie(cookieName, cookie);
          }
        }
        return true;
      },
      /**
       * perform.refreshUserCookie
       * Refreshes the user cookie content if it's older than 24hrs
       * @param cookieName (string) the name of the user cookie
       * @param ageTimestamp (integer) the time after which the cookie is considered stale
       * @return (boolean) true if the cookie has been refreshed
       * @return (boolean) false if the cookie is younger than 24hrs
       */
      refreshUserCookie: function (cookieName, ageTimestamp) {
        ageTimestamp = ageTimestamp !== undefined ? ageTimestamp : 86400000;
        cookieName = cookieName !== undefined ? cookieName : 'user';

        var currentTimestamp = perform.getCurrentTimeStamp();
        var creationTimestamp = perform.getChip(cookieName, "timestamp");

        // If the cookie is older then 1 day
        // make sure the data is not stale
        if ((currentTimestamp - creationTimestamp) > ageTimestamp && creationTimestamp !== false) {
          $.ajax({
            type: 'GET',
            url: '/system/userrefresh'
          });

          return true;
        } else {
          return false;
        }
      },
     /**
      * perform.setLogoutRedirect
      * Set address for redirect after logout
      * @param redirectUrl (string) address for redirect
      * @return (object) perform - perform object
      */
      setLogoutRedirect: function (redirectUrl) {
        logoutRedirect = redirectUrl;
        return this;
      },
     /**
      * perform.insertTracking
      * Injects a script tag with the tracking url
      * that increments the view counter for the asset
      * @param domain (string) tracking domain
      * @param outlet (string) tracking outlet ID
      * @param options (object) optional parameters - article uuid, etc.
      * @return (boolean) false if missing parameters
      */
      insertTracking: function (domain, outlet, options) {
        var path = "/tracking/create/";
        var defaults = {
          uuid: "",
          type: "article",
          act: "view"
        }
        if (typeof options == 'object') {
          o = extend(defaults, options);
        } else {
          o = defaults;
        }
        
        if (domain !== undefined && outlet !== undefined && o.uuid !== "") {
          var base = domain + path + outlet + "?";
          var url = base + serialize(o);
            
          var firstScriptTag = document.getElementsByTagName('script')[0];
          var newScriptTag = document.createElement('script');
          newScriptTag.type = 'text/javascript';
          newScriptTag.async = true;
          newScriptTag.src = base + serialize(o);
            
          firstScriptTag.parentNode.insertBefore(newScriptTag, firstScriptTag);
            
          return true;
        }else{
          return false;
        }
      }
    };/*END of return*/
  })();
